<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
	</body>
	<script>
		// 1. forEach 方法
		// 练习题 1：根据条件修改对象属性
		// 有一个包含用户信息的数组，每个用户信息是一个 JSON 对象，包含 name、age 和 isVerified 字段。使用 forEach 方法将年龄大于 30 且未验证（isVerified 为 false）的用户的 isVerified 字段设置为 true。

		const users = [{
				name: 'Alice',
				age: 25,
				isVerified: false
			},
			{
				name: 'Bob',
				age: 32,
				isVerified: false
			},
			{
				name: 'Charlie',
				age: 40,
				isVerified: true
			},
			{
				name: 'David',
				age: 28,
				isVerified: false
			}
		];

		function fun1(arr) {
			arr.forEach((obj) => {
				if (obj.isVerified == false && obj.age > 30) {
					obj.isVerified = true
				}
			})
		}
		// 练习题 2：计算对象数组中某属性的加权和
		// 假设有一个包含商品信息的数组，每个商品对象包含 price（价格）和 quantity（数量）字段。使用 forEach 方法计算所有商品的总价值（价格乘以数量的总和）。

		const products = [{
				price: 10,
				quantity: 2
			},
			{
				price: 20,
				quantity: 3
			},
			{
				price: 15,
				quantity: 4
			}
		];

		function fun2(arr) {
			var total = 0;
			arr.forEach((obj) => {
				total = Object.values(obj).reduce((a, b) => {
					return a * b;
				}, 1)
				console.log(total);
			})

		}
		// 练习题 3： 按条件分组对象
		// 有一个包含学生信息的数组， 每个学生对象包含 name、 grade（ 年级） 和 score（ 分数） 字段。 使用 forEach 方法将学生按年级分组， 并计算每个年级的平均分数。

		const students = [{
				name: 'Eve',
				grade: 9,
				score: 80
			},
			{
				name: 'Frank',
				grade: 10,
				score: 90
			},
			{
				name: 'Grace',
				grade: 9,
				score: 75
			},
			{
				name: 'Henry',
				grade: 10,
				score: 85
			}
		];

		function fun3(arr) {
			var gra = {};
			arr.forEach((obj) => {
				if (gra.hasOwnProperty(obj.grade) == false) {
					gra[obj.grade] = {
						num: 1,
						avg: obj.score
					}
				} else {
					gra[obj.grade].num++;
					gra[obj.grade].avg += obj.score;
				}

			})
			for (var n in gra) {
				gra[n].avg = gra[n].avg / gra[n].num;
			}
			return gra;
		}

		// 2. filter 方法
		// 练习题 1：筛选符合多个条件的对象
		// 有一个包含员工信息的数组，每个员工对象包含 name、department（部门）、salary（薪水）和 yearsOfExperience（工作年限）字段。使用 filter 方法筛选出销售部门（department 为 'Sales'），薪水大于 5000 且工作年限超过 3 年的员工。

		const employees = [{
				name: 'Ivy',
				department: 'Sales',
				salary: 6000,
				yearsOfExperience: 4
			},
			{
				name: 'Jack',
				department: 'HR',
				salary: 4500,
				yearsOfExperience: 2
			},
			{
				name: 'Kelly',
				department: 'Sales',
				salary: 5500,
				yearsOfExperience: 3
			},
			{
				name: 'Leo',
				department: 'Engineering',
				salary: 7000,
				yearsOfExperience: 5
			}
		];

		function fun4(arr) {
			return arr.filter((obj) => { //返回筛选后的数组
				return obj.department === 'Sales'
			})
		}
		//console.log(	fun4(employees));
		// 练习题 2：筛选包含特定子对象的对象数组
		// 有一个包含文章信息的数组，每个文章对象包含 title、author 和 tags（标签数组）字段。使用 filter 方法筛选出包含 'JavaScript' 标签的文章。

		const articles = [{
				title: 'Article 1',
				author: 'Mia',
				tags: ['HTML', 'CSS']
			},
			{
				title: 'Article 2',
				author: 'Noah',
				tags: ['JavaScript', 'React']
			},
			{
				title: 'Article 3',
				author: 'Olivia',
				tags: ['Python', 'Django']
			},
		];

		function fun5(arr) {
			return arr.filter(({
				tags
			}) => { //返回符合的数组元素的数组
				return tags.some((str) => str === 'JavaScript' ? true : false);
			})
		}
		//	练习题 3：筛选满足复杂条件的嵌套对象
		//	有一个包含订单信息的数组，每个订单对象包含 orderId、customer（客户对象，包含 name 和 loyaltyPoints 字段）和 items（商品项数组
		//，每个商品项包含 productName 和 price 字段）。使用 filter 方法筛选出客户忠诚度积分大于 100 且订单中有价格超过 200 的商品的订单。
		const orders = [{
				orderId: 1,
				customer: {
					name: 'Peter',
					loyaltyPoints: 120
				},
				items: [{
						productName: 'Product A',
						price: 150
					},
					{
						productName: 'Product B',
						price: 250 //200
					}
				]
			},
			{
				orderId: 2,
				customer: {
					name: 'Quinn',
					loyaltyPoints: 80
				},
				items: [{
						productName: 'Product C',
						price: 100
					},
					{
						productName: 'Product D',
						price: 180
					}
				]
			},
			{
				orderId: 3,
				customer: {
					name: 'Ryan',
					loyaltyPoints: 150 //>100
				},
				items: [{
						productName: 'Product E',
						price: 50
					},
					{
						productName: 'Product F',
						price: 120
					}
				]
			}
		];

		function fun6(arr) {
			return arr.filter(({
				customer,
				items
			}) => {
				return (customer.loyaltyPoints > 100 && items.some((obj) => obj.price > 200)) ? true : false;
			});
		}
		//		3. some 方法,记得过滤filter
		//	练习题 1：检查数组中是否有满足多个条件的对象
		//	有一个包含书籍信息的数组，每个书籍对象包含 title、author、year（出版年份）和 genre（类型）字段。使用 some 方法检查数组中是否有 2020 年之后出版的科幻小说。

		const books = [{
				title: 'Book 1',
				author: 'Sam',
				year: 2018,
				genre: 'Fiction'
			},
			{
				title: 'Book 2',
				author: 'Tina',
				year: 2021,
				genre: 'Science Fiction'
			},
			{
				title: 'Book 3',
				author: 'Uma',
				year: 2019,
				genre: 'Mystery'
			}
		];

		function fun7(arr) {
			return arr.some((obj) => obj.year > 2020)
		}
		//练习题 2：检查对象数组中是否有特定属性值的组合
		//有一个包含项目信息的数组，每个项目对象包含 projectName、teamSize（团队规模）和 budget（预算）字段。使用 some 方法检查数组中是否有团队规模大于 5 且预算超过 10000 的项目。

		const projects = [{
				projectName: 'Project A',
				teamSize: 3,
				budget: 8000
			},
			{
				projectName: 'Project B',
				teamSize: 6,
				budget: 12000
			},
			{
				projectName: 'Project C',
				teamSize: 4,
				budget: 9000
			}
		];

		function fun8(arr) {
			return arr.some((obj) => (obj.teamSize > 5 && obj.budget > 10000))
		}
		//	练习题 3：检查嵌套对象数组中是否有满足条件的元素
		//有一个包含班级信息的数组，每个班级对象包含 className 和 students（学生数组，每个学生对象包含 name 和 score 字段）。
		//使用 some 方法检查是否有班级中存在分数超过 90 的学生。

		const classes = [{
				className: 'Class 1',
				students: [{
						name: 'Victor',
						score: 85
					},
					{
						name: 'Wendy',
						score: 88
					}
				]
			},
			{
				className: 'Class 2',
				students: [{
						name: 'Xavier',
						score: 92
					},
					{
						name: 'Yvonne',
						score: 87
					}
				]
			},
			{
				className: 'Class 3',
				students: [{
						name: 'Zoe',
						score: 80
					},
					{
						name: 'Adam',
						score: 83
					}
				]
			}
		];

		function fun9(arr) {
			return arr.some(({
				students
			}) => {
				for (var obj of students) {
					if (obj.score >= 90) {
						return true;
					}
				}
				return false;
			})
		}
		//Array.isArray 方法
		//练习题 1：递归检查嵌套对象中是否包含数组
		//有一个复杂的嵌套对象，使用 Array.isArray 方法递归检查该对象中是否包含数组。

		const nestedObject = {
			a: 1,
			b: {
				c: [1, 2, 3],
				d: {
					e: 4
				}
			},
			f: 'hello'
		};

		function fun10(obj) {
			arr = Object.values(obj)
			for (var x in arr) {
				if (Array.isArray(arr[x]) == true) {
					return true;
				}
				if (typeof arr[x] == 'object') {
					return fun10(arr[x]);
				}
			}
			return false;
		}
console.log( fun10(nestedObject));
		// 练习题 2：过滤数组，只保留包含数组属性的对象
		// 有一个对象数组，每个对象可能包含不同的属性，使用 Array.isArray 方法过滤出包含数组属性的对象。

		const objectArray = [{
				prop1: 1,
				prop2: [1, 2]
			},
			{
				prop3: 'hello'
			},
			{
				prop4: {
					subProp: [3, 4]
				}
			}
		];


		function fun11(arr) {
			function fun(obj) {
				for (var x in obj) {
					if (Array.isArray(obj[x]) == true) {
						return true;
					}
					if (typeof obj[x] == 'object') {
						return fun(obj[x]);
					}
				}
				return false;
			}
			return arr.filter(fun)
		}
		// 5. trim 方法
		// 练习题 1：去除对象属性值两端的空格
		// 有一个包含用户信息的对象数组，每个用户对象包含 name、email 和 phone 字段。使用 trim 方法去除每个用户信息中字符串属性值两端的空格。

		const usersInfo = [{
				name: '   John   ',
				email: '  john@example.com  ',
				phone: '  1234567890  '
			},
			{
				name: '   Jane   ',
				email: '  jane@example.com  ',
				phone: '  0987654321  '
			}
		];

		function fun12(arr) {
			arr.forEach((obj) => {
				for (var x in obj) {
					obj[x] = obj[x].trim();
				}
			})
		}
		//	练习题 2：过滤对象数组，去除属性值为空字符串（去除空格后）的对象
		//	有一个包含任务信息的对象数组，每个任务对象包含 taskName、description 和 status 字段。使用 trim 方法过滤掉 taskName 去除空格后为空字符串的任务。

		const tasks = [{
				taskName: '   ',
				description: 'Do something',
				status: 'In Progress'
			},
			{
				taskName: 'Task 1',
				description: 'Complete project',
				status: 'Completed'
			},
			{
				taskName: '   Task 2   ',
				description: 'Review code',
				status: 'Pending'
			}
		];

		function fun13(arr) {
			return arr.filter((obj) => {
				if (Number(obj.taskName.trim()) == 0) {
					return 0;
				} else {
					return 1;
				}
			})
		}
		//练习题 3：对对象数组中的特定属性进行去重（去除空格后）
		//有一个包含联系人信息的对象数组，每个联系人对象包含 name 和 email 字段。使用 trim 方法去除 email 属性值两端的空格，并对 email 进行去重。
		//使用对象去重,reduce;
		const contacts = [{
				name: 'Tom2',
				email: '  tom@example.com  '
			},
			{
				name: 'Jerry',
				email: 'jerry@example.com'
			},
			{
				name: 'Tom1',
				email: 'tom@example.com'
			}
		];

		function fun14(arr) {
			var email = {};
			arr.forEach((obj) => {
				email[obj.name] = obj.email.trim();
			})
			while(contacts.length!=0){
				contacts.pop();
			}
			for (var x in email) {
				contacts.push({
					name: x,
					email: email[x]
				})
			}
		}
	fun14(contacts)
	console.log(contacts);
	//asdaskjaksldljskfakqewr
	//asdjsakjjklskqweoisfdzjksiaios
	</script>
</html>